package com.boe.csb.core.service.csb;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.alibaba.csb.console.sdk.Result;
import com.alibaba.csb.sdk.HttpCaller;
import com.alibaba.csb.sdk.HttpCallerException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.boe.csb.core.common.CsbConstants;
import com.boe.csb.core.common.exception.CSBErrorCode;
import com.boe.csb.core.common.exception.CSBException;
import com.boe.csb.core.common.status.CertificationStatus;
import com.boe.csb.core.common.status.PublishStatusEnum;
import com.boe.csb.core.common.status.UserPicType;
import com.boe.csb.core.common.utils.CsbApiCaller;
import com.boe.csb.core.common.utils.GsonUtils;
import com.boe.csb.core.common.utils.MailTemplate;
import com.boe.csb.core.dao.BoeApiInfoCriteria;
import com.boe.csb.core.dao.BoeApiInfoMapper;
import com.boe.csb.core.dao.BoeApiPopularCriteria;
import com.boe.csb.core.dao.BoeApiPopularMapper;
import com.boe.csb.core.dao.BoeUserFtpCriteria;
import com.boe.csb.core.dao.BoeUserFtpMapper;
import com.boe.csb.core.dao.BoeUserMapper;
import com.boe.csb.core.entity.po.BoeApiInfo;
import com.boe.csb.core.entity.po.BoeApiPopular;
import com.boe.csb.core.entity.po.BoeUser;
import com.boe.csb.core.entity.po.BoeUserFtp;
import com.boe.csb.core.service.SendMailService;
import com.boe.csb.core.service.api.BoeApiInfoService;
import com.boe.csb.core.service.api.BoeApiPopularService;
import com.boe.csb.core.service.user.BoeUserService;
import com.ctc.wstx.util.StringUtil;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;

/**
 * Created by tianxiang.luo on 16/12/4.
 */

@Service("csbManagerApiService")
public class CsbManagerApiService {

    private Logger logger = LoggerFactory.getLogger(CsbManagerApiService.class);

    @Autowired
    private BoeUserService boeUserService;
    @Autowired
    private BoeUserMapper boeUserMapper;
    @Autowired
    private BoeApiInfoMapper boeApiInfoMapper;
    @Autowired
    private BoeApiPopularService boeApiPopularService;
    @Autowired
    private BoeApiInfoService boeApiInfoService;
    @Autowired
    private BoeUserFtpMapper boeUserFtpMapper;
    @Autowired
    private BoeApiPopularMapper boeApiPopularMapper;
    @Autowired
    private SendMailService sendMailService;

    private static final String csbId = CsbApiCaller.CSB_ID;

    //查看已经发布的服务
    private static final String FIND_SERVICES = "/api/services/find";
    //批量起停服务
    private static final String UPDATE_SERVICE_STATUS = "/api/services/status";
    //查看服务详情
    private static final String FIND_SINGLE_SERVICE = "/api/service/find";
    //删除服务
    private static final String API_SERVICE_DELETE = "api/service/delete";
    //管理员修改服务状态
    private static final String ACTIVE_SERVICE = "/api/services/status";


    /**
     * 发布服务
     *
     * @paramw
     */
    public Result publishService(String userId, String data) throws IOException {
    	String userId_bak = userId;
        //后端填充必要数据,先转化
        JSONObject object = JSON.parseObject(data);
        
    	//如果json串中包含服务id，这条服务为返回修改,管理员以用户名义修改服务信息
        Object serverId = object.get("id");
        if(serverId != null){
        	BoeApiInfo boeApiInfo = boeApiInfoMapper.loadApiInfo(Long.valueOf(serverId.toString()));
        	Object obj = object.get("policyHandler");
        	if(obj == null){
            	object.put("policyHandler", "accept");
            }
        	String userId1 = boeApiInfo.getUserId().toString();
        	if(!userId1.equals(userId)){
        		logger.info("用户{}以用户{}名义修改服务：{}",userId1,userId,boeApiInfo.getApiName());
        		userId = userId1;
        	}
        }
        
        //假如传过来id 则说明用户是修改服务,需要判断 服务是否属于该用户
        BoeUser boeUser = boeUserMapper.selectByPrimaryKey(Long.valueOf(userId));
        String publishServiceAPI = "/api/service/addOrUpdate";
        //判断是否有发布权限
        if (!CertificationStatus.ALLOW.getStatus().equals(boeUser.getAuditStatus())) {
            throw new CSBException(CSBErrorCode.NO_AUTH, "用户没有发布权限");
        }
        //判断是否用户已经创建分组
        Long projectId = this.findProject(userId);
        if (projectId == null) {
            //如果没有
            createProject(userId);
            projectId = findProject(userId);
        }
        Map<String, String> userInfoMap = new HashMap<>();
        userInfoMap.put("csbId", CsbApiCaller.CSB_ID);
        userInfoMap.put("userId", userId);

      

        object.put("csbId", CsbApiCaller.CSB_ID);
        object.put("userId", userId);
        object.put("status", PublishStatusEnum.APPLYING.getValue());
        object.put("ownerId", userId);
        object.put("projectId", projectId);
        Integer sequenceId = (Integer) object.remove("sequenceId");
        Integer categoryId = (Integer) object.remove("categoryId");
        boolean isAudit = (Boolean) object.remove("isAudit");
        logger.info("这是即将向csb提交的服务JSON,提交人{},服务{}", userId, GsonUtils.object2String(GsonUtils.string2JsonObject(JSON.toJSONString(object))));
        Result result = CsbApiCaller.callCsbPostApi(publishServiceAPI, userInfoMap, JSON.toJSONString(object));
        if (result.isSuccess()) {
            Long servId = result.getData().getLong("servId");
            //更新ftp 根据userId判断一下
            BoeUserFtpCriteria ftpCriteria = new BoeUserFtpCriteria();
            ftpCriteria.createCriteria().andIdEqualTo(Long.valueOf(sequenceId)).andUseridEqualTo(Long.valueOf(userId_bak));
            BoeUserFtp ftp = new BoeUserFtp();
            ftp.setCsbApiId(servId);
            ftp.setUserid(Long.valueOf(userId));
            ftp.setType(UserPicType.servicePic.name());
            boeUserFtpMapper.updateByExampleSelective(ftp, ftpCriteria);

            // 发布服务的时候 存到本地 关联 类目
            BoeApiInfo info = new BoeApiInfo();
            info.setApiName(object.getString("serviceName"));
            info.setApiDesc(object.getString("description"));
            info.setAlias(object.getString("alias"));
            info.setIsAudit(isAudit);
            //获取  服务商logo
            info.setApiPic("/api/user/getImg?userId=" + boeUser.getId() + "&type=" + UserPicType.servicePic.name() + "&csbApiId=" + servId);
            info.setGmtCreate(new Date());
            info.setGmtModified(new Date());
            info.setCategoryId(Long.valueOf(categoryId));
            info.setUserId(Long.valueOf(userId));
            
            info.setCsbApiId(servId);
            
            BoeApiInfo boeinfo = boeApiInfoMapper.loadApiInfo(servId);
            if(boeinfo != null){
            	info.setId(boeinfo.getId());
            	info.setApiStatus(PublishStatusEnum.ACTIVE.getStatus());
            	boeApiInfoMapper.updateByPrimaryKeySelective(info);
            }else{
            	info.setApiStatus(PublishStatusEnum.APPLYING.getStatus());
            	boeApiInfoMapper.insert(info);
            }
           
            
        }
        return result;
    }


    /**
     * 查询服务组id
     */
    public Long findProject(String userId) {
        BoeUser boeUser = boeUserService.findBoeUser(userId);
        String projectName = boeUser.getProjectName();
        String apiName = "api/project/get";
        Map<String, String> queryMap = new HashMap<>();
        queryMap.put("csbId", CsbApiCaller.CSB_ID);
        queryMap.put("userId", userId);
        queryMap.put("projectName", projectName);
        Result result = CsbApiCaller.callCsbGetApi(apiName, queryMap);
        JSONArray jsonArray = result.getData().getJSONArray("projects");
        if (!CollectionUtils.isEmpty(jsonArray)) {
            JSONObject project = jsonArray.getJSONObject(0);
            return project.getLong("id");
        }
        return null;
    }

    /**
     * 创建服务组
     * boeUserId
     */
    public void createProject(String userId) {
        String createProjectAPI = "/api/project/createorupdate";
        BoeUser boeUser = boeUserMapper.selectByPrimaryKey(Long.valueOf(userId));
        String projectName = "project" + userId;
        int status = 0;//服务组激活状态
        Map<String, String> createMap = new HashMap<>();
        createMap.put("csbId", CsbApiCaller.CSB_ID);
        createMap.put("userId", userId);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("projectName", "project" + userId);
        jsonObject.put("status", status);
        jsonObject.put("ownerId", userId);
        jsonObject.put("projectOwnerName", boeUser.getCompanyName());
        jsonObject.put("projectOwnerEmail", boeUser.getEmail());
        jsonObject.put("projectOwnerPhoneNum", boeUser.getPhone());

        Result result = CsbApiCaller.callCsbPostApi(createProjectAPI, createMap, jsonObject.toJSONString());
        if (result.isSuccess()) {
            //把服务组名备份到用户表
            BoeUser updateBoeUser = new BoeUser();
            updateBoeUser.setGmtModified(new Date());
            updateBoeUser.setProjectName(projectName);
            updateBoeUser.setId(Long.valueOf(userId));
            boeUserMapper.updateByPrimaryKeySelective(updateBoeUser);
        }
    }


    /**
     * 查看自己发布的服务
     */
    public Result ownPublishedService(String userId, Integer pageNum, String serviceName, String alias) {
        Map<String, String> findMap = new HashMap<>();
        findMap.put("csbId", csbId);
        findMap.put("userId", userId);
        findMap.put("pageNum", String.valueOf(pageNum));
        if (serviceName != null) {
            findMap.put("serviceName", serviceName);
        }
        if (alias != null) {
            findMap.put("alias", alias);
        }
        return CsbApiCaller.callCsbGetApi(FIND_SERVICES, findMap);
    }


    /**
     * 删除自己发布的服务
     *
     * @param userId
     * @return
     */
    public Result deleteOwnServices(Long userId, Long serviceId, String serviceName) {
        Map<String, String> deleteMap = new HashMap<>();
        deleteMap.put("csbId", CsbApiCaller.CSB_ID);
        deleteMap.put("userId", String.valueOf(userId));
        deleteMap.put("serviceId", String.valueOf(serviceId));
        deleteMap.put("serviceName", serviceName);
        Result result = CsbApiCaller.callCsbPostApi(API_SERVICE_DELETE, deleteMap, "");
        if (result.isSuccess()) {
            BoeApiInfoCriteria criteria = new BoeApiInfoCriteria();
            criteria.createCriteria().andCsbApiIdEqualTo(serviceId);
            BoeApiInfo info = new BoeApiInfo();
            info.setApiStatus(PublishStatusEnum.DELETE.getStatus());
            boeApiInfoMapper.updateByExampleSelective(info, criteria);

            BoeApiPopularCriteria popularCriteria = new BoeApiPopularCriteria();
            popularCriteria.createCriteria().andCsbApiIdEqualTo(serviceId);
            BoeApiPopular apiPopular = new BoeApiPopular();
            apiPopular.setStatus(PublishStatusEnum.DELETE.getStatus());
            boeApiPopularMapper.updateByExampleSelective(apiPopular,popularCriteria);
        }
        return result;
    }


    /**
     * 查找单个服务
     */
    public Result findSingleService(String userId, Long serviceId) {
        Map<String, String> queryMap = new HashMap<>();
        queryMap.put("csbId", CsbApiCaller.CSB_ID);
        queryMap.put("userId", userId);
        queryMap.put("serviceId", String.valueOf(serviceId));
        queryMap.put("skipCallInfo", "true");
        return CsbApiCaller.callCsbGetApi(FIND_SINGLE_SERVICE, queryMap);
    }


    /**
     * @param userId
     * @return
     */
    public boolean checkServiceBelongUser(Long serviceId, String userId) {
        BoeApiInfoCriteria boeApiInfoCriteria = new BoeApiInfoCriteria();
        boeApiInfoCriteria.createCriteria().andUserIdEqualTo(Long.valueOf(userId)).andCsbApiIdEqualTo(serviceId);
        long count = boeApiInfoMapper.countByExample(boeApiInfoCriteria);
        return count > 0;
    }

    public Result findProjects(String userId) {
        String findProjectsAPI = "/api/projects/find";
        Map<String, String> map = new HashMap<>();
        map.put("csbId", CsbApiCaller.CSB_ID);
        map.put("userId", userId);
        map.put("pageNum", "1");
        return CsbApiCaller.callCsbGetApi(findProjectsAPI, map);
    }


    /**
     * 获取凭证 map
     *
     * @return
     */
    public Map<String, String> findCredentials(String userId) {
        String apiName = "/api/credentials/list";
        int pageNum = 1;
        JSONObject object = new JSONObject();
        object.put("userId", userId);
        object.put("pageNum", pageNum);
        String credentialsJsonObject = CsbApiCaller.callCsbPostApi(apiName, null, "").getData().toJSONString();
        JsonObject returnJsonObject = GsonUtils.string2JsonObject(credentialsJsonObject);
        JsonObject data = returnJsonObject.getAsJsonObject("data");
        JsonArray credentialList = data.getAsJsonArray("credentialList");
        if (credentialList != null) {
            JsonObject credential = (JsonObject) credentialList.get(0);
            JsonObject currentCredential = credential.getAsJsonObject("currentCredential");
            String secretKey = currentCredential.get("secretKey").getAsString();
            String accessKey = currentCredential.get("accessKey").getAsString();
            Map<String, String> map = new HashMap<>();
            map.put("secretKey", secretKey);
            map.put("accessKey", accessKey);
            return map;
        }
        return null;
    }

    /**
     * 更新csb服务状态
     *
     * @param userId
     * @param serviceIds
     * @param status
     * @return
     */
    public Result updateServiceStatus(String userId, List<Long> serviceIds, String status) {
        Map<String, String> map = new HashMap<>();
        map.put("userId", userId);
        map.put("csbId", CsbApiCaller.CSB_ID);
        JSONObject object = new JSONObject();
        //不是启用就是禁用
        Integer stat = PublishStatusEnum.ACTIVE.getStatus().equals(status) ? 1 : 0;
        object.put("status", stat);
        object.put("serviceIds", serviceIds);
        Result result = CsbApiCaller.callCsbPostApi(ACTIVE_SERVICE, map, JSON.toJSONString(object));
        if (result.isSuccess()) {
            Boolean approveFlag = stat == 1;
            //启用禁用要修改本地的服务
            boeApiPopularService.updatePopularServices(approveFlag, serviceIds);
            boeApiInfoService.updateApiStatus(serviceIds, status);
        }
        return result;
    }

    /**
     * 调试服务
     */
    public String debugService(String userId, JSONObject data) throws HttpCallerException {
        String result;
        BoeUser boeUser = boeUserMapper.selectByPrimaryKey(Long.valueOf(userId));
        if (!CertificationStatus.ALLOW.getStatus().equals(boeUser.getAuditStatus())) {
            throw new CSBException(CSBErrorCode.NO_AUTH, "");
        }
        String ak = boeUser.getAk();
        String sk = boeUser.getSk();
        String requestURL = CsbConstants.CSB_API_ADDRESS;
        String API_NAME = (String) data.remove("apiName");
        String version = (String) data.remove("version");
        String method = (String) data.remove("method");
        Map<String, String> paramsMap = new HashMap<>();
        JSONObject params = data.getJSONObject("params");
        for (String key : params.keySet()) {
            paramsMap.put(key, params.getString(key));
        }
        if ("POST".equalsIgnoreCase(method)) {
            result = HttpCaller.doPost(requestURL, API_NAME, version, paramsMap, ak, sk);
        } else {
            result = HttpCaller.doGet(requestURL, API_NAME, version, paramsMap, ak, sk);
        }
        return result;
    }


    public JSONObject queryServiceParam(Long serviceId) {
        Result result = findSingleService(CsbApiCaller.CSB_ADMIN_ID, serviceId);
        JSONObject service = result.getData().getJSONObject("service");
        JSONArray inputParamList = service.getJSONArray("inputParamList");
        JSONArray params = new JSONArray();
        String apiName = service.getString("serviceName");
        for (Object o : inputParamList) {
            params.add(o);
        }
        JSONObject data = new JSONObject();
        data.put("params", params);
        data.put("serviceVersion",service.getString("serviceVersion"));
        data.put("errList",service.getJSONArray("errList"));
        data.put("apiName", apiName);
        data.put("accessEndpointJSON",service.getString("accessEndpointJSON"));
        return data;
    }
    
    /**
     * 发布和订阅时发送邮件给响应管理员
     * @param type
     */
    public void sendAdminUserMail(String type,String serviceId,String userId){
    	if(MailTemplate.RELEASE.equals(type)){
    		String emailContent = MailTemplate.generateServicePublicMail(type,serviceId, userId);
    		//发布服务，发送通知邮件到系统管理员-20170224 xinghe
    		List<String> list = boeUserMapper.getReleaseAdminEmail();
    		if(!(list == null || list.size() <= 0)){
    			logger.info("用户发布服务审批通知邮件：{},审批人:{}",emailContent,list.get(0));
    			for(int i=0;i<list.size();i++){
        			sendMailService.asyncSendMail(list.get(i), CsbConstants.APPROVAL_NOTICE_MAIL_SUBJECT, emailContent);
        		}
    		}
    		
    	}else if(MailTemplate.SUBSCRIBE.equals(type)){
    		Map<String,String> map = boeApiInfoMapper.getServiceUserEmail(Long.valueOf(serviceId));
    		logger.info("订阅发布服务邮件服务名：{}",map.toString());
    		String emailContent = MailTemplate.generateServicePublicMail(type,map.get("api_name"), userId);
    		//订阅服务，发送通知邮件到系统管理员-20170224 xinghe
    		List<String> list = boeUserMapper.getSubscribeAdminEmail();
    		if(!(list == null || list.size() <= 0)){
    			logger.info("用户发布服务审批通知邮件：{},审批人:{}",emailContent,list.get(0));
    			for(int i=0;i<list.size();i++){
        			sendMailService.asyncSendMail(list.get(i), CsbConstants.APPROVAL_NOTICE_MAIL_SUBJECT, emailContent);
        		}
    		}
    		String email = map.get("email");
    		if(!list.contains(email)){
    			sendMailService.asyncSendMail(email, CsbConstants.APPROVAL_NOTICE_MAIL_SUBJECT, emailContent);
    		}
    		
    	}
    }
}
